package com.caffeinatedbliss.nanowrimo;

import org.nanowrimo.ws.domain.WordCountListEntry;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: pshawke
 * Date: Nov 20, 2006
 * Time: 3:44:46 PM
 * This file was using Monsanto resources and is the sole property of
 * Monsanto.  Any duplication of the code and/or logic is a direct
 * infringement of Monsanto's copyright.
 */
public class Burndown implements DynamicImageGenerator {
  private static final int CURVE_RADIUS = 15;
  public static final int WIDTH = 192;
  public static final int HEIGHT = 117;

  public static final int TOP = 16;
  public static final int LEFT = 20;

  public static final Color AXIS_COLOUR = new Color(0xaa, 0xaa, 0xaa);
  public static final Color DASH_COLOUR = new Color(0xcc, 0xcc, 0xcc);
  public static final Color GRAPH_AREA_LIGHT_COLOUR = new Color(0xee, 0xee, 0xee);
  public static final Color GRAPH_AREA_DARK_COLOUR = new Color(0xcc, 0xcc, 0xff);
  public static final Color TREND_LINE_COLOUR = new Color(0x33, 0xcc, 0x33);

  public static final Color LIGHTEST_GREY = new Color(0xf0, 0xf0, 0xf0);
  public static final Color NOT_SO_LIGHTEST_GREY = new Color(0xbb, 0xbb, 0xdd);
  private static final GradientPaint GRADIENT = new GradientPaint(CURVE_RADIUS, CURVE_RADIUS,
    LIGHTEST_GREY, 2 * CURVE_RADIUS, CURVE_RADIUS * 7, NOT_SO_LIGHTEST_GREY, false);

  public static final Color GREY_BORDER = new Color(0xbb, 0xbb, 0xbb);
  public static final Color DK_GREY_BORDER = new Color(0x99, 0x99, 0x99);
  private static final GradientPaint OUTSIDE_GRADIENT = new GradientPaint(CURVE_RADIUS, CURVE_RADIUS,
    GREY_BORDER, 2 * CURVE_RADIUS, CURVE_RADIUS * 7, DK_GREY_BORDER, false);

  private BufferedImage bufferedImage;

  public Burndown(WordCountListEntry[] entries) {
    bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
    Graphics2D gr = (Graphics2D) bufferedImage.getGraphics();

    gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    drawFilledRectangleWithCurvedCorners(gr);

    drawGraphAxes(gr);

    drawExpectedTrend(gr);

    drawWordcount(entries, gr);

    gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

    gr.dispose();
  }

  private void drawWordcount(WordCountListEntry[] entries, Graphics2D gr) {
    int[] points = convertToArrayOfWordcountsRemaining(entries);
    int[] x = new int[points.length];
    int[] y = new int[points.length];
    int index = 0;
    for (int i = 0; i < points.length; i++) {
      int point = 50000 - points[i];
      if (point != 50000) {
        x[index] = LEFT + 2 + (i * 5);
        y[index] = (int) (TOP + 80 - (point * 3.0 / 2000.0));
        index++;
      }
    }
    gr.setColor(Color.BLACK);
    gr.drawPolyline(x, y, index);
  }

  private void drawExpectedTrend(Graphics2D gr) {
    gr.setColor(TREND_LINE_COLOUR);
    gr.drawLine(LEFT + 1, TOP + 8, LEFT + 152, TOP + 79);
  }

  public BufferedImage getGraphImage() {
    return bufferedImage;
  }

  private int[] convertToArrayOfWordcountsRemaining(WordCountListEntry[] entries) {
    int[] amounts = new int[30];
    GregorianCalendar gcal = new GregorianCalendar();
    for (int i1 = 0; i1 < entries.length; i1++) {
      gcal.setTime(entries[i1].getDate());
      amounts[gcal.get(Calendar.DAY_OF_MONTH) - 1] = entries[i1].getWordcount();
    }

    int found = 0;
    for (int i11 = 29; i11 >= 0; i11--) {
      if (amounts[i11] > 0) {
        found = i11;
        break;
      }
    }

    int[] returnAmount = new int[found + 1];
    System.arraycopy(amounts, 0, returnAmount, 0, found + 1);
    return returnAmount;
  }

  private void drawFilledRectangleWithCurvedCorners(Graphics2D g) {
    g.setPaint(GRADIENT);
    g.fillRoundRect(0, 0, WIDTH - 1, HEIGHT - 1, 2 * CURVE_RADIUS, 2 * CURVE_RADIUS);

    g.setPaint(OUTSIDE_GRADIENT);
    g.drawRoundRect(0, 0, WIDTH - 1, HEIGHT - 1, 2 * CURVE_RADIUS, 2 * CURVE_RADIUS);
  }

  private void drawGraphAxes(Graphics2D gr) {
    GradientPaint paint = new GradientPaint(0, 75, GRAPH_AREA_LIGHT_COLOUR, 0, 0, GRAPH_AREA_DARK_COLOUR);
    gr.setPaint(paint);
    gr.fillRect(LEFT, TOP + 3, 152, 77);
    gr.setColor(GRAPH_AREA_LIGHT_COLOUR);
    gr.drawRect(LEFT, TOP + 3, 152, 77);

    gr.setColor(AXIS_COLOUR);
    gr.drawLine(LEFT, TOP + 3, LEFT, TOP + 80);
    gr.drawLine(LEFT, TOP + 80, LEFT + 152, TOP + 80);

    Stroke solid = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0);
    Stroke dash = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[]{2, 2}, 1);
    Font foo = new Font("dialog", Font.PLAIN, 9);
    gr.setFont(foo);
    FontMetrics fm = gr.getFontMetrics(foo);
    int ht = (fm.getDescent() + fm.getHeight()) / 2;
    for (int i = 0; i < 5; i++) {
      gr.setColor(DASH_COLOUR);
      gr.setStroke(dash);
      gr.drawLine(LEFT + 2, TOP + 5 + (15 * i), LEFT + 152, TOP + 5 + (15 * i));

      gr.setColor(AXIS_COLOUR);
      gr.setStroke(solid);
      gr.drawLine(LEFT - 1, TOP + 5 + (15 * i), LEFT + 1, TOP + 5 + (15 * i));

      gr.setColor(Color.GRAY);
      gr.drawString("" + (50 - i * 10), LEFT - 12, TOP + 5 + (15 * i) + ht);
    }

    for (int i = 1; i < 5; i++) {
      gr.setColor(AXIS_COLOUR);
      gr.drawLine(LEFT + 2 + (i * 35), TOP + 79, LEFT + 2 + (i * 35), TOP + 81);

      gr.setColor(Color.GRAY);
      gr.drawString("" + (i * 7), LEFT - 2 + (i * 35), TOP + 83 + ht);
    }
  }
}
